#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include <errno.h>
#include <ctype.h>
#include <sys/stat.h>

#include "../include/linkedlist.h"
#include "../include/narytree.h"
#include "../include/hashtable.h"
#include "../include/binarysearchtree.h"
#include "../include/error_code.h"
#include "../include/vfs.h"
#include "../include/global.h"
#include "../include/vfs_errorcodes.h"
#include "../include/printhelper.h"

global* globaldata;
int ismounted;
int bstcount, updatecount;
char bst_path[1024][200];
file_d* prepareFileDescriptor(char *path, char *filename, char *filetype) {
	file_d* dir = (file_d*) malloc(sizeof(file_d));
	dir->file_size = 0;
	sprintf(dir->file_name, "%s", filename);
	sprintf(dir->file_path, "%s", path);
	sprintf(dir->file_type, "%s", filetype);
	dir->file_block_no = -1;
	dir->start_addr = -1;
//	dir->file_blocks[0] = 12;
	return dir;
}

/*---------------------------Creates VFS-----------------------------------*/

int vfscreate(char* label, long int size) {
	//checking "DATA_FILE_ALREADY_EXISTS" 1
	errno = 0;
	FILE* p = fopen(label, "rb");
	if (errno == 0) {
		//fclose(p);
		return CREATEVFS_DATA_FILE_ALREADY_EXISTS;
	}

	if (p != NULL )
		fclose(p);

	//when erro == 13 Permission denied  "CANNOT_CREATE_DATAFILE" 2
	if (errno == 13)
		return CREATEVFS_CANNOT_CREATE_DATAFILE;

	//checking "INVALID_CHARACTER_IN_NAME" 4
	int i;
	if (strlen(label) > 30)
		return CREATEVFS_VFS_LABEL_TOO_LARGE;
	for (i = 0; i < strlen(label); i++) {
		if (label[i] == '/')
			return CREATEVFS_INVALID_CHARACTER_IN_NAME;
	}

	//checking "INVALID_SIZE" 5
	if (size < 1 || size > 1024)
		return CREATEVFS_INVALID_SIZE;

	vfs main_header;
	file_d fd;
	list l;
	int flag = 0;

	//when errno =2 path does not exist  "CANNOT_CREATE_DATAFILE" 2
	if (errno == 2)
		flag = 1;
	FILE* fp = fopen(label, "wb+");

	//when errno =28 checking "NOT_ENOUGH_MEMORY" 3
	if (errno == 28) {
		remove(label);
		return CREATEVFS_NOT_ENOUGH_MEMORY;
	}

	//when errno =2 path does not exist  "CANNOT_CREATE_DATAFILE" 2
	if (errno == 2 && flag != 1) {
		remove(label);
		return CREATEVFS_CANNOT_CREATE_DATAFILE;
	}

	/*---------Adding data in the main header---------*/

	strcpy(main_header.vfs_label, label);
	main_header.vfs_size = size * 1024;
	main_header.num_f_d_used = 0;
	main_header.block_size = sizeof(block);
	main_header.no_of_blocks = (int) main_header.vfs_size
			/ main_header.block_size;
	main_header.max_num_f_d = main_header.no_of_blocks;
	main_header.freelistPoint = sizeof(main_header) + 1;
	main_header.file_d_arrayPoint = sizeof(main_header)
			+ (sizeof(struct free_list) * main_header.no_of_blocks) + 1;
	main_header.datablkPoint = sizeof(struct virtual_file_system)
			+ ((sizeof(struct file_descriptor)) * main_header.max_num_f_d)
			+ (sizeof(struct free_list) * main_header.no_of_blocks) + 1;

	/*---------writing main header---------*/

	fwrite(&main_header, sizeof(main_header), 1, fp);

	if (errno == 28) {
		remove(label);
		return CREATEVFS_NOT_ENOUGH_MEMORY;
	}
	/*----------writing free List-------------*/

	fseek(fp, main_header.freelistPoint, SEEK_SET);
	if (errno == 28) {
		remove(label);
		return CREATEVFS_NOT_ENOUGH_MEMORY;
	}
	for (i = 0; i < main_header.no_of_blocks; i++) {
		l.block_num = i;
		l.isFull = 'n';
		fwrite(&l, sizeof(l), 1, fp);
		if (errno == 28) {
			remove(label);
			return CREATEVFS_NOT_ENOUGH_MEMORY;
		}
	}

	/*---------writing file descriptors---------*/

	fseek(fp, main_header.file_d_arrayPoint, SEEK_SET);
	if (errno == 28) {
		remove(label);
		return CREATEVFS_NOT_ENOUGH_MEMORY;
	}
	//Initializing file descriptor
	fd.file_name[0] = '\0';
	fd.file_path[0] = '\0';
	fd.file_type[0] = '\0';
	fd.file_size = -1;

	for (i = 0; i < main_header.max_num_f_d; i++) {
		fd.start_addr = main_header.datablkPoint
				+ (i * sizeof(struct data_block));
		fd.file_block_no = i;
		fwrite(&fd, sizeof(fd), 1, fp);
		if (errno == 28) {
			remove(label);
			return CREATEVFS_NOT_ENOUGH_MEMORY;
		}
	}

	/*---------writing data blocks---------*/
	fseek(fp, main_header.datablkPoint, SEEK_SET);
	block blk;
	for (i = 0; i < main_header.no_of_blocks; i++) {
		//blk.next = ftell(fp) + main_header.block_size;
		blk.data[0] = '\0';
		fwrite(&blk, sizeof(blk), 1, fp);
		if (errno == 28) {
			remove(label);
			return CREATEVFS_NOT_ENOUGH_MEMORY;
		}
	}

	/*---------Empty space---------

	 //long int freespace= size - ((sizeof(struct virtual_file_system) + main_header.max_num_f_d* sizeof(struct file_descriptor) + main_header.no_of_blocks * main_header.block_size ) + 1);
	 long int freespace = size
	 - ((sizeof(struct data_block)) * main_header.no_of_blocks);
	 char ch = '\0';
	 printf("\nfreespace is %lu", freespace);
	 if (freespace != 0) {
	 //		printf("first freespace point is %lu", ftell(fp));
	 for (i = 0; i < freespace; i++) {
	 fwrite(&ch, sizeof(ch), 1, fp);
	 }
	 }*/

	fclose(fp);
	return 0;
}

int vfsmount(char* label) {
	//checking mounted status
	if (ismounted == 1) {
		return MOUNTVFS_VFS_ALREADY_MOUNTED;
	}
	int j;
	FILE *fp;
	vfs main_header;
	errno = 0;
	//initilizing all data structure
	globaldata->root_nary = nary_root_init();
	hashtable_init(&globaldata->hash_table);
	globaldata->root_bst = NULL;
	file_d* bstfd = prepareFileDescriptor("", "", "DIR");
	bst_insert(&globaldata->root_bst, bstfd);
	file_d* fd = (file_d*) malloc(sizeof(file_d));
	//file_d *fd;// = (file_d*) malloc(sizeof(file_d));
	//Open a binary file in read mode

	fp = fopen(label, "rb");
	if (fp == NULL )
		return MOUNTVFS_DATA_FILE_NOT_FOUND;

	//set mounted true
	ismounted = 1;
	if (!fread(&main_header, sizeof(main_header), 1, fp)) {
		fclose(fp);
		return MOUNTVFS_CANNOT_READ_FROM_FILE;
	}
	strcpy(globaldata->vfs_label, main_header.vfs_label);
	globaldata->vfs_size = main_header.vfs_size;
	globaldata->no_of_blocks = main_header.no_of_blocks;
	globaldata->block_size = main_header.block_size;
	globaldata->max_num_f_d = main_header.max_num_f_d;
	globaldata->num_f_d_used = main_header.num_f_d_used;
	globaldata->datablkPoint = main_header.datablkPoint;
	globaldata->freelistPoint = main_header.freelistPoint;
	globaldata->file_d_arrayPoint = main_header.file_d_arrayPoint;
	/*if (fseek(fp, main_header.file_d_arrayPoint, SEEK_SET)) {
	 fclose(fp);
	 return MOUNTVFS_CANNOT_READ_FROM_FILE;
	 }*/
	if (errno != 0) {
		fclose(fp);
		return MOUNTVFS_CANNOT_READ_FROM_FILE;
	}
	fseek(fp, main_header.file_d_arrayPoint, SEEK_SET);
	//Read fd and load it on nary tree, BST, hash-table one by one
	for (j = 0; j <= globaldata->num_f_d_used; j++) {
		if (!fread(fd, sizeof(file_d), 1, fp)) {
			fclose(fp);
			return MOUNTVFS_CANNOT_READ_FROM_FILE;
		}
		if (strcmp(fd->file_name, "") != 0) {
			bst_insert(&globaldata->root_bst, fd);
			hashtable_insert(&globaldata->hash_table, fd);
			nary_insert_node(&globaldata->root_nary, fd);
		}

	}
	/*printf("\nn-ary tree:\n");
	 nary_print(globaldata->root_nary);
	 printf("\nhash table:\n");
	 hashtable_print(&globaldata->hash_table);
	 printf("\nInorder traversal for BST:\n");
	 inorder(globaldata->root_bst);*/
	fclose(fp);
	return 0;
}

void unmount_setglobals() {
	ismounted = 0;
	globaldata->root_nary = NULL;
	globaldata->root_bst = NULL;

}

int unmount_travesal_nary(t_node* root, int count, file_d** result) {
	if (root != NULL ) {
		count++;

		//(*node)->left = (*node)->right = NULL;
		unmount_travesal_nary(root->siblings, count, result);
		*(result + count) = root->data;
		unmount_travesal_nary(root->child, count, result);
	}
	return count;
}
int unmount_travesal_bst(bst_node* root, file_d* result) {
	if (root != NULL ) {
		bstcount++;
		sprintf(result[bstcount].file_path, "%s", root->data->file_path);
		result[bstcount].file_block_no = root->data->file_block_no;
		sprintf(result[bstcount].file_name, "%s", root->data->file_name);
		result[bstcount].file_size = root->data->file_size;
		result[bstcount].start_addr = root->data->start_addr;
		sprintf(result[bstcount].file_type, "%s", root->data->file_type);
		unmount_travesal_bst(root->left, result);
		unmount_travesal_bst(root->right, result);
	}
	return bstcount;
}

int vfsunmount(char* label) {
	FILE *fp;
	vfs main_header;
	if (ismounted != 1) {
		return UNMOUNTVFS_VFS_NOT_MOUNTED;
	}
	if (ismounted == 1) {
		if (strcmp(globaldata->vfs_label, label) != 0)
			return UNMOUNTVFS_DATA_FILE_NOT_FOUND;
	}
	fp = fopen(label, "wb+");
	if (fp == NULL )
		return UNMOUNTVFS_DATA_FILE_NOT_FOUND;

	/*if (fseek(fp, main_header.file_d_arrayPoint, SEEK_SET)) {
	 unmount_setglobals();
	 fclose(fp);
	 return UNMOUNTVFS_CANNOT_WRITE_TO_FILE;
	 }*/
	strcpy(main_header.vfs_label, globaldata->vfs_label);
	main_header.vfs_size = globaldata->vfs_size;
	main_header.no_of_blocks = globaldata->no_of_blocks;
	main_header.block_size = globaldata->block_size;
	main_header.max_num_f_d = globaldata->max_num_f_d;
	main_header.num_f_d_used = globaldata->num_f_d_used;
	main_header.datablkPoint = globaldata->datablkPoint;
	main_header.freelistPoint = globaldata->freelistPoint;
	main_header.file_d_arrayPoint = globaldata->file_d_arrayPoint;
	//errno = 0;
	if (!fwrite(&main_header, sizeof(main_header), 1, fp)) {
		//printf("error is %s", strerror(errno));
		unmount_setglobals();
		fclose(fp);
		return UNMOUNTVFS_CANNOT_WRITE_TO_FILE;
	}
	rewind(fp);
	/*if (!fseek(fp, main_header.freelistPoint, SEEK_SET)) {
	 unmount_setglobals();
	 fclose(fp);
	 return UNMOUNTVFS_CANNOT_WRITE_TO_FILE;
	 }*/
	int i;
	/*list l;
	 for (i = 0; i < main_header.no_of_blocks; i++) {
	 l.block_num = i;
	 l.isFull = 'n';
	 if (!fwrite(&l, sizeof(l), 1, fp)) {
	 unmount_setglobals();
	 fclose(fp);
	 return UNMOUNTVFS_CANNOT_WRITE_TO_FILE;
	 }
	 }*/
	fseek(fp, main_header.file_d_arrayPoint, SEEK_SET);
	//file_d* fd = (file_d*) malloc(sizeof(file_d));

	file_d* result = (file_d*) malloc(sizeof(file_d) * main_header.max_num_f_d);
	for (i = 0; i < main_header.max_num_f_d; i++) {
		//sprintf(result[i].file_path, "%s", "");
		result[i].file_path[0] = '\0';
		result[i].file_block_no = i;
		//sprintf(result[i].file_name, "%s", "");
		result[i].file_name[0] = '\0';
		result[i].file_size = 0;
		result[i].start_addr = main_header.datablkPoint
				+ (i * sizeof(struct data_block));
		//sprintf(result[i].file_type, "%s", "");
		result[i].file_type[0] = '\0';
	}
	// = unmount_travesal_nary(globaldata->root_nary, -1, result);
	bstcount = -1;
	int count = unmount_travesal_bst(globaldata->root_bst, result);
	file_d fd;
	//inorder(globaldata->root_bst);
	/*for (i = 0; i <= globaldata->num_f_d_used; i++) {
	 printf("\nresult %d - file path is  %s and file_name is %s\n", i,
	 result[i].file_path, result[i].file_name);
	 }*/
	for (i = 0; i <= count; i++) {
		/*	fd.start_addr = main_header.datablkPoint
		 + (i * sizeof(struct data_block));
		 fd.file_block_no = i;*/
		/*char file_path1[100];
		 file_path1[0]='\0';*/
		char *file_path1 = (char*) malloc(sizeof(char) * MAX_PATH_SIZE);
		char * first = strchr(result[i].file_path, '/');
		char * last = strrchr(result[i].file_path, '/');
		if (strcmp(first, last) == 0) {
			strncpy(file_path1, first, 1);
			file_path1[strlen(last)] = '\0';
		} else {
			strncpy(file_path1, first, last - first);
			file_path1[last - first] = '\0';
		}
		strcpy(result[i].file_path, file_path1);
		file_d fd;
		fd.file_block_no = result[i].file_block_no;
		strcpy(fd.file_name, result[i].file_name);
		strcpy(fd.file_path, result[i].file_path);
		fd.file_size = result[i].file_size;
		strcpy(fd.file_type, result[i].file_type);
		fd.start_addr = result[i].start_addr;
		if (strcmp(result[i].file_name, "") != 0)
			if (!fwrite(&fd, sizeof(fd), 1, fp)) {
				unmount_setglobals();
				fclose(fp);
				return UNMOUNTVFS_CANNOT_WRITE_TO_FILE;
			}
		/*if (!fwrite(&result, sizeof(fd), 1, fp)) {
		 unmount_setglobals();
		 fclose(fp);
		 return UNMOUNTVFS_CANNOT_WRITE_TO_FILE;
		 }*/
	}
	for (i = count + 1; i < main_header.max_num_f_d; i++) {
		if (!fwrite(&result[i], sizeof(fd), 1, fp)) {
			unmount_setglobals();
			fclose(fp);
			return UNMOUNTVFS_CANNOT_WRITE_TO_FILE;
		}
	}
	fclose(fp);
	unmount_setglobals();
	return 0;
}
char* removeslash(char* data) {
	if (strlen(data) == 1) {
		return data;
	} else {
		char* path = (char *) malloc(sizeof(char) * MAX_PATH_SIZE);
		char c = (data)[strlen(data) - 1];
		if (c == '/') {
			strncpy(path, data, strlen(data) - 1);
			path[strlen(data) - 1] = '\0';
			return path;
		} else
			return data;
	}
}

/*--------------------------Make's Directory----------------------*/

int vfsmakedir(char parent_path[MAX_PATH_SIZE],
		char dir_name[MAX_FILE_NAME_SIZE]) {

	//checking mount status
	if (ismounted != 1) {
		return MAKEDIR_VFS_NOT_MOUNTED;
	}
	if (globaldata->num_f_d_used >= globaldata->max_num_f_d) {
		return MAKEDIR_FILESYSTEM_FULL;
	}

	int i;
	//checking INVALID_CHARACTER_IN_DIRNAME
	/*if (strlen(dir_name) > MAX_FILE_NAME_SIZE || strlen(dir_name) == 0)
	 return INVALID_CHARACTER_IN_FILENAME;*/
	for (i = 0; i < strlen(dir_name); i++) {
		if (dir_name[i] == '/')
			return MAKEDIR_INVALID_CHARACTER_IN_DIRNAME;
	}
	//two continous / should not be there
	for (i = 0; i < strlen(parent_path) - 1; i++) {
		if (parent_path[i] == '/' && parent_path[i + 1] == '/')
			return MAKEDIR_INVALID_CHARACTER_IN_DIRNAME;
	}
	parent_path = removeslash(parent_path);
	if (parent_path[0] != '/') {
		return 11;
	}
	//int l1 = strlen(parent_path);
	//int l2 = strlen(dir_name);
	//char qname[MAX_PATH_SIZE];
	char *qname = (char*) malloc((sizeof(char)) * MAX_PATH_SIZE);
	qname[0] = '\0';
	strcpy(qname, parent_path);
	if (strcmp(parent_path, "/") != 0)
		strcat(qname, "/");
	strcat(qname, dir_name);
	/*char* qname = (char*) malloc(sizeof(char) * (l1 + l2 + 1));
	 strcpy(qname, parent_path);
	 qname = removeslash(qname);
	 if (strcmp(parent_path, "/") != 0)
	 strcat(qname, "/");
	 strcat(qname, dir_name);*/
	file_d* fd = prepareFileDescriptor(qname, dir_name, "DIR");
	bst_node *find;
	find = bst_find(globaldata->root_bst, qname);
	//checking DIRECTORY_ALREADY_EXISTS
	if (find != NULL )
		return MAKEDIR_DIRECTORY_ALREADY_EXISTS;
	//inserting in data structures
	char dir[MAX_FILE_SIZE], path[MAX_PATH_SIZE];
	int dcount = 0, pcount = 0, pathdone = 0, first = 0;
	char fullpath[MAX_PATH_SIZE];
	fullpath[0] = '\0';
	parent_path = removeslash(parent_path);
	strcat(fullpath, parent_path);
	if (strcmp(fullpath, "/") != 0)
		strcat(fullpath, "/");
	strcat(fullpath, dir_name);
	strcat(fullpath, "/");
	for (i = 0; i < strlen(fullpath); i++) {
		if (globaldata->num_f_d_used == globaldata->max_num_f_d) {
			return MAKEDIR_FILESYSTEM_FULL;
		}
		char c = fullpath[i];
		if (c == '/' && i != 0) {
			char file_p[100];
			char * first = strchr(path, '/');
			char * last = strrchr(path, '/');
			if (strcmp(first, last) == 0) {
				strncpy(file_p, last, 1);
			} else {
				strncpy(file_p, first, last - first);
			}
			file_p[last - first] = '\0';
			char dirnametemp[MAX_FILE_SIZE];
			strncpy(dirnametemp, dir, dcount);
			dirnametemp[dcount] = '\0';
			if (file_p[0] == '\0')
				strcpy(file_p, "/");
			file_d* fd = prepareFileDescriptor(file_p, dirnametemp, "DIR");
			bst_node* find1 = bst_find(globaldata->root_bst, path);
			if (find1 == NULL ) {
				globaldata->num_f_d_used = globaldata->num_f_d_used + 1;
				bst_insert(&globaldata->root_bst, fd);
				hashtable_insert(&globaldata->hash_table, fd);
				nary_insert_node(&globaldata->root_nary, fd);
			}
			dcount = 0;
			//free(dirnametemp);
		} else if (i != 0) {

			dir[dcount] = c;
			dcount++;
		}
		path[pcount] = c;
		pcount++;
		path[pcount] = '\0';

	}
	/*parent_path = removeslash(parent_path);
	 file_d* fdnarry = prepareFileDescriptor(parent_path, dir_name, "DIR");
	 bst_insert(&globaldata->root_bst, fdnarry);
	 hashtable_insert(&globaldata->hash_table, fdnarry);
	 nary_insert(&globaldata->root_nary, fdnarry);*/
	//printf("inorder is \n");
	//inorder(globaldata->root_bst);
	return 0;
}

int vfsdeletedir(char *P1) {
	P1 = removeslash(P1);
	if (ismounted != 1) {
		return MAKEDIR_VFS_NOT_MOUNTED;
	}
	if (strcmp(P1, "/") == 0)
		return DELETEDIR_DIRECTORY_IS_NOT_EMPTY;
	int res = -1;
	/*printf("\ninorder in deletedir\n");
	 inorder(globaldata->root_bst);*/
	char *dir_Name;
	char *dir_Path;
	bst_node* fd;
	dir_Path = (char *) malloc(sizeof(char) * 1024);
	fd = bst_find(globaldata->root_bst, P1);
	if (fd == NULL )
		return DELETEDIR_CANNOT_FIND_SPECIFIED_DIR;
	if (strcmp(fd->data->file_type, "DIR") != 0)
		return DELETEDIR_CANNOT_FIND_SPECIFIED_DIR;
	char* temp = strrchr(fd->data->file_path, '/');
	char* file_path = (char*) malloc(sizeof(char) * MAX_PATH_SIZE);
	int value = temp - fd->data->file_path + 1;
	strncpy(file_path, fd->data->file_path, value);
	file_path = removeslash(file_path);
	file_d* fd1 = prepareFileDescriptor(file_path, fd->data->file_name, "DIR");
	res = nary_delete_node(&globaldata->root_nary, fd1);
	if (res == NOT_EMPTY)
		return DELETEDIR_DIRECTORY_IS_NOT_EMPTY;
	res = hashtable_delete_fd(&globaldata->hash_table, fd->data);
	res = bst_delete(&globaldata->root_bst, fd->data);
	//res = remove_fd_(&globaldata->hash_table, globaldata->root_nary, globaldata->root_bst, fd->data);
	globaldata->num_f_d_used--;
	return 0;
}

int vfsmovedir(char *P1, char *P2) {
	if (ismounted != 1) {
		return MOVEDIR_VFS_NOT_MOUNTED;
	}
	if (strcmp(P1, "/") == 0)
		return DELETEDIR_DIRECTORY_IS_NOT_EMPTY;
	P1 = removeslash(P1);
	P2 = removeslash(P2);

	/*printf("inorder in movedir before");
	 inorder(globaldata->root_bst);*/
	char *p22 = (char*) malloc((sizeof(char)) * MAX_PATH_SIZE);
	strcpy(p22, P2);
	char *src_Path, *dest_Path;
	src_Path = (char*) malloc(sizeof(char) * MAX_PATH_SIZE);
	dest_Path = (char*) malloc(sizeof(char) * MAX_PATH_SIZE);
	strcpy(src_Path, P1);
	strcpy(dest_Path, P2);
	char *src_Dir;
	src_Dir = (char*) malloc(sizeof(char) * CHARSIZE);
	bst_node *src_fd, *des_fd, *temp_src_fd;
	// int ret=move_Function(datastr->ntree,src_Path,dest_Path,"DIR");
	/*  if(mainstr->is_mounted!=5)
	 return 8;*/
	/*printf("bst inorder in movedir\n");
	 inorder(globaldata->root_bst);*/
	src_fd = bst_find(globaldata->root_bst, P1);
	des_fd = bst_find(globaldata->root_bst, P2);
	if (src_fd == NULL )
		return MOVEDIR_CANNOT_FIND_SPECIFIED_SOURCEDIR;
	if (des_fd == NULL )
		return MOVEDIR_CANNOT_FIND_SPECIFIED_DESTINATIONDIR;
	if (strcmp(src_fd->data->file_type, "DIR") != 0)
		return MOVEDIR_SOURCE_CANNOT_BE_FILE;
	if (strcmp(des_fd->data->file_type, "DIR") != 0)
		return MOVEDIR_DESTINATION_CANNOT_BE_FILE;
	src_Dir = strrchr(P1, '/');
	strcat(P2, src_Dir);
	temp_src_fd = bst_find(globaldata->root_bst, P2);
	if (temp_src_fd != NULL )
		return MOVEDIR_DESTINATION_ALREADY_HAVE_SOURCE_DIR;
	if (strncmp(P1, p22, strlen(P1)) == 0 && p22[strlen(P1)] == '/')
		return MOVEDIR_CANNOT_MOVE_PARENT_TO_CHILD_DIR;
	nary_move_node(globaldata->root_nary, src_Path, dest_Path);
	update_bst_ht(P1, p22);
	char* lst = strrchr(P1, '/');
	char temp[MAX_PATH_SIZE];
	strcpy(temp, ++lst);
	file_d* bst_fd_insert = prepareFileDescriptor(p22, temp, "DIR");
	bst_insert(&globaldata->root_bst, bst_fd_insert);
	file_d* bst_fd_del = prepareFileDescriptor(P1, temp, "DIR");
	bst_delete(&globaldata->root_bst, bst_fd_del);
	return 0;
}

int vfslistdir(char *P1, int P2, char *P3) {
	if (ismounted != 1) {
		return LISTDIR_VFS_NOT_MOUNTED;
	}
	P1 = removeslash(P1);
	int ret = -1;
	if (P2 > 1 || P2 < 0)
		return LISTDIR_INVALID_FLAG;
	bst_node* find = bst_find(globaldata->root_bst, P1);
	if (find == NULL )
		return LISTDIR_CANNOT_FIND_SPECIFIED_PATH_OR_DIR;
	ret = nary_list_dir(globaldata->root_nary, P2, P1, P3);
	if (ret != 0)
		return LISTDIR_CANNOT_FIND_SPECIFIED_PATH_OR_DIR;
	return 0;
}

int vfsaddfile(char *P1, char *P2, char *P3) {
	//printf("\ngsdhgsfgsdjgfsgdfgsgdd\n");
	//inorder(globaldata->root_bst);
	if (ismounted != 1) {
		return ADDFILE_FILE_VFS_NOT_MOUNTED;
	}
	P1 = removeslash(P1);
	char ch, qname[MAX_PATH_SIZE];
	FILE *source, *fp;
	list l;
	int i;

	//checking "INVALID_CHARACTER_IN_NAME" 2
	if (strlen(P2) > MAX_FILE_NAME_SIZE || strlen(P2) == 0)
		return ADDFILE_INVALID_CHARACTER_IN_FILENAME;
	for (i = 0; i < strlen(P2); i++) {
		if (P2[i] == '/')
			return ADDFILE_INVALID_CHARACTER_IN_FILENAME;
	}
	//checking FILE_SYSTEM_FULL
	if (globaldata->max_num_f_d == globaldata->num_f_d_used) {
		return ADDFILE_FILE_SYSTEM_FULL;
	}
	strcpy(qname, P1);
	if (strcmp(P1, "/") != 0)
		strcat(qname, "/");
	strcat(qname, P2);

	//checking "FILE_ALREADY_EXISTS" 3
	bst_node *find;
	find = bst_find(globaldata->root_bst, qname);
	if (find != NULL )
		return ADDFILE_FILE_ALREADY_EXISTS;

	bst_node *dir;
	dir = bst_find(globaldata->root_bst, P1);
	if (dir == NULL )
		return ADDFILE_DIRECTORY_DOES_NOT_EXIST; //added by self, no appropriate error code found.

	//checking CANNOT_WRITE_TO_DATAFILE;
	//printf("\n%s\n",P3);
	source = fopen(P3, "rb");
	if (source == NULL )
		return ADDFILE_SOURCE_NOT_FOUND; //added by self, no appropriate error code found.

	//checking  FILE_TOO_LARGE
	fseek(source, ftell(source), SEEK_END);
	long int size_of_file = ftell(source);
	rewind(source);
	if (size_of_file - 1 > MAX_FILE_SIZE)
		return ADDFILE_FILE_TOO_LARGE;

	fp = fopen(globaldata->vfs_label, "rb+");
	char *type = getFileType(P2);
	file_d* fd = prepareFileDescriptor(P1, P2, type); //creating file descriptor without full path
	fseek(fp, globaldata->freelistPoint, SEEK_SET);
	for (i = 0; i < (globaldata->no_of_blocks); i++) {
		fread(&l, sizeof(list), 1, fp);
		if (l.isFull == 'n') {
			fd->file_block_no = l.block_num;
			break;
		}
	}
	//writing the updated data of the list back in the file
	fseek(fp, globaldata->freelistPoint + ((l.block_num) * sizeof(list)),
			SEEK_SET);
	l.isFull = 'y';
	fwrite(&l, sizeof(list), 1, fp);

	fd->start_addr = globaldata->datablkPoint
			+ ((fd->file_block_no) * globaldata->block_size);

	//creating data block and writing it to the vfs
	block blk;
	fread(&(blk.data), size_of_file - 1, 1, source);
	fd->file_size = size_of_file - 1;
	fseek(fp, fd->start_addr, SEEK_SET);
	errno = 0;

	// checking CANNOT_WRITE_TO_DATAFILE
	fwrite(&blk, sizeof(block), 1, fp);
	if (strcmp(strerror(errno), "Success") != 0)
		return ADDFILE_CANNOT_WRITE_TO_DATAFILE;

	//printf("Open error: %s\n\n", strerror(errno));
	fclose(fp);
	fclose(source);
	globaldata->num_f_d_used = globaldata->num_f_d_used + 1;

	//inserting in data structures
	//printf("values to be stored in nary are %s, %s", fd->file_path,fd->file_name);
	int res = nary_insert_node(&globaldata->root_nary, fd);
	hashtable_insert(&globaldata->hash_table, fd);
	bst_insert(&globaldata->root_bst, fd);

	/*fp = fopen(globaldata->vfs_label, "rb+");
	 block blk2;
	 fseek(fp, fd->start_addr, SEEK_SET);
	 fread(&blk2, sizeof(block), 1, fp);
	 printf("\n data added is %s", blk2.data);
	 printf("start address is %lu", fd->start_addr);*/

	return 0;

}

int vfslistfile(char *P1, char *P2) {
	if (ismounted != 1) {
		return LISTFILE_VFS_NOT_MOUNTED;
	}
	block blk;
	FILE *fp, *fp1;
	bst_node *find;

	//checking LISTFILE_NOT_A_TEXT_FILE
	char *type = getFileType(P1);
	if (strcmp(type, "txt") != 0)
		return LISTFILE_NOT_A_TEXT_FILE;
	if (strcmp(type, "") == 0)
		return LISTFILE_NOT_A_TEXT_FILE;

	//checking LISTFILE_SOURCE_FILE_PATH_NOT_FOUND
	find = bst_find(globaldata->root_bst, P1);
	//printf("\nP1 searched in find is  %s\n",find->data->file_path);

	if (find == NULL )
		return LISTFILE_SOURCE_FILE_PATH_NOT_FOUND;

	//checking LISTFILE_CANNOT_CREATE_OUTPUTFILE
	fp1 = fopen(P2, "w");
	if (fp1 == NULL )
		return LISTFILE_CANNOT_CREATE_OUTPUTFILE;

	fp = fopen(globaldata->vfs_label, "rb");
	if (find != NULL ) {
		fseek(fp, find->data->start_addr, SEEK_SET);
		fread(&blk, sizeof(block), 1, fp);
	}
	//fputs(blk.data, fp1);
	fwrite(&blk, find->data->file_size, 1, fp1);
	fclose(fp1);
	fclose(fp);
	return 0;

}

int vfsupdatefile(char *P1, char *P2) {
	if (ismounted != 1) {
		return UPDATEFILE_VFS_NOT_MOUNTED;
	}
	char data[MAX_FILE_SIZE];
	FILE *source, *fp;
	//checking INTERNAL_FILE_NOT_FOUND and getting the fd for the corresponding file path
	bst_node *find;
	find = bst_find(globaldata->root_bst, P1);
	if (find == NULL )
		return UPDATEFILE_INTERNAL_FILE_NOT_FOUND;

	//checking INCORRECT_FILE_FORMAT
	//char *type;
	//type = getFileType(P2);
	/*	if (strcmp(type, find->data->file_type) != 0)
	 return UPDATEFILE_INCORRECT_FILE_FORMAT;*/

	//checking  EXTERNAL_FILE_NOT_FOUND;
	source = fopen(P2, "r");
	if (source == NULL )
		return UPDATEFILE_EXTERNAL_FILE_NOT_FOUND;

	fp = fopen(globaldata->vfs_label, "rb+");

	//checking EXTERNAL_FILE_TOO_LARGE
	fseek(source, ftell(source), SEEK_END);
	long int size_of_file = ftell(source);
	rewind(source);
	if (size_of_file - 1 > MAX_FILE_SIZE)
		return UPDATEFILE_EXTERNAL_FILE_TOO_LARGE;

	//creating data block and writing it to the vfs
	block blk;
	fread(&(blk.data), size_of_file - 1, 1, source);
	fseek(fp, find->data->start_addr, SEEK_SET);
	errno = 0;
	fwrite(&blk, sizeof(block), 1, fp);
	if (strcmp(strerror(errno), "Success") != 0)
		return UPDATEFILE_CANNOT_WRITE_TO_DATAFILE;
	find->data->file_size = size_of_file - 1;
	//printf("Open error: %s\n\n", strerror(errno));
	fclose(fp);
	fclose(source);
	return 0;
}

char* getFileType(char* P1) {
	char* pos = strrchr(P1, '.');
	char* type = (char*) malloc(sizeof(char) * 100);
	type[0] = '\0';
	if (!pos)
		return type;
	strcpy(type, pos + 1);
	return type;

	/*
	 char tokens[MAX_PATH_SIZE][MAX_FILE_NAME_SIZE];
	 globaldata->num_f_d_used = globaldata->num_f_d_used + 1;
	 char* token;
	 char filepath[20];
	 int num_token = 0;
	 sprintf(filepath, "%s", P1);
	 token = strtok(filepath, "/");
	 while (token != NULL) {
	 strcpy(tokens[num_token], token);
	 token = strtok(NULL, "/");
	 num_token++;
	 }
	 sprintf(filepath, "%s", tokens[num_token - 1]);
	 num_token = 0;
	 token = strtok(filepath, ".");
	 while (token != NULL) {
	 strcpy(tokens[num_token], token);
	 token = strtok(NULL, "/");
	 num_token++;
	 }
	 return tokens[num_token - 1];*/
}

char* getFileName(char* P1) {
	char* pos = strrchr(P1, '/');
	pos++;
	char* type = (char*) malloc(sizeof(char) * 100);
	type[0] = ' ';
	if (pos == NULL )
		return type;
	strcpy(type, pos);
	return type;
	/*char tokens[MAX_PATH_SIZE][MAX_FILE_NAME_SIZE];
	 globaldata->num_f_d_used = globaldata->num_f_d_used + 1;
	 char* token;
	 char filepath[20];
	 int num_token = 0;
	 sprintf(filepath, "%s", P1);
	 token = strtok(filepath, "/");
	 while (token != NULL) {
	 strcpy(tokens[num_token], token);
	 token = strtok(NULL, "/");
	 num_token++;
	 }
	 return tokens[num_token - 1];*/
}

int vfsremovefile(char *P1) {
	if (ismounted != 1) {
		return REMOVEFILE_VFS_NOT_MOUNTED;
	}
	FILE *fp;
	block blk;
	/*printf("\ninorder in removefile before\n");
	 inorder(globaldata->root_bst);*/
	fp = fopen(globaldata->vfs_label, "rb");
	//printf("inorder in removefile:\n");
	//inorder(globaldata->root_bst);
	//Deleting the data from the block
	bst_node *find = NULL;
	find = bst_find(globaldata->root_bst, P1);

	if (find == NULL )
		return REMOVEFILE_CANNOT_FIND_SPECIFIED_FILE;
	if (strcmp(find->data->file_type, "DIR") == 0)
		return REMOVEFILE_CANNOT_FIND_SPECIFIED_FILE;

	file_d* duplicate = (file_d*) malloc(sizeof(file_d));
	sprintf(duplicate->file_name, "%s", find->data->file_name);
	sprintf(duplicate->file_path, "%s", find->data->file_path);
	duplicate->file_size = find->data->file_size;
	duplicate->start_addr = find->data->start_addr;
	duplicate->file_block_no = find->data->file_block_no;
	sprintf(duplicate->file_type, "%s", find->data->file_type);

	fseek(fp, duplicate->start_addr, SEEK_SET);
	blk.data[0] = '\0';
	fwrite(&blk, sizeof(block), 1, fp);

	//decrementing num of used fd's and changing corresponding free list as empty
	globaldata->num_f_d_used = globaldata->num_f_d_used - 1;
	list l;
	fseek(fp,
			globaldata->freelistPoint
					+ ((duplicate->file_block_no) * sizeof(list)), SEEK_SET);
	l.isFull = 'n';
	l.block_num = duplicate->file_block_no;
	fwrite(&l, sizeof(list), 1, fp);

	//deleting from data structures
	char file_path[100];
	char * first = strchr(duplicate->file_path, '/');
	char * last = strrchr(duplicate->file_path, '/');
	if (strcmp(first, last) == 0) {
		strncpy(file_path, last, 1);
	} else {
		strncpy(file_path, first, last - first);
	}

	file_d* fd1 = prepareFileDescriptor(file_path, duplicate->file_name,
			duplicate->file_type);

	//printf("\ndeleting from nary %s and %s and whole path is %s",fd1->file_path, fd1->file_name, find->data->file_path);
	int res = nary_delete_node(&globaldata->root_nary, fd1);
	/*	hashtable_print(&globaldata->hash_table);*/
	hashtable_delete_fd(&globaldata->hash_table, duplicate);
	/*	hashtable_print(&globaldata->hash_table);*/
	bst_delete(&globaldata->root_bst, duplicate);
	/*printf("\ninorder in removefile after\n");
	inorder(globaldata->root_bst);*/
	return 0;
}

int vfsmovefile(char *P1, char *P2) {
	if (ismounted != 1)
		return MOVEFILE_VFS_NOT_MOUNTED;
	FILE *fp;
	char *name;
	bst_node *source_path;
	fp = fopen(globaldata->vfs_label, "rb+");

	//checking MOVEFILE_CANNOT_FIND_SOURCEFILE and getting the fd for the corresponding file path
	source_path = bst_find(globaldata->root_bst, P1);
	if (source_path == NULL )
		return MOVEFILE_CANNOT_FIND_SOURCEFILE;
	if (strcmp(source_path->data->file_type, "DIR") == 0)
		return MOVEFILE_CANNOT_FIND_SOURCEFILE;

	//checking  MOVEFILE_CANNOT_FIND_DESTINATION_PATH;
	//P2 = removeslash(P2);
	char file_path1[100];
	char * first = strchr(P2, '/');
	char * last = strrchr(P2, '/');
	if (strcmp(first, last) == 0) {
		strncpy(file_path1, last, 1);
	} else {
		strncpy(file_path1, first, last - first);
		file_path1[last - first] = '\0';
	}
	bst_node *destination_path;
	destination_path = bst_find(globaldata->root_bst, file_path1);
	if (destination_path == NULL )
		return MOVEFILE_CANNOT_FIND_DESTINATION_PATH;

	//preparing new fd
	char *type = getFileType(P2);
	name = getFileName(P2);
	// printf("\n\nfile name is %s\n", name);
	file_d* fd = prepareFileDescriptor(file_path1, name, type);
	fd->start_addr = source_path->data->start_addr;
	fd->file_size = source_path->data->file_size;
	fd->file_block_no = source_path->data->file_block_no;

	/* printf("\nsource path: size is %lu, startaddr is %lu, blk num is %lu ",
	 source_path->data->file_size,source_path->data->start_addr,source_path->data->file_block_no);*/

	char* temp1 = strrchr(source_path->data->file_path, '/');
	char file_path[100];
	int value1 = temp1 - source_path->data->file_path; // + 1;
	strncpy(file_path, source_path->data->file_path, value1);
	file_d* fd1 = prepareFileDescriptor(file_path, source_path->data->file_name,
			type);
	fd1->start_addr = source_path->data->start_addr;
	fd1->file_size = source_path->data->file_size;
	fd1->file_block_no = source_path->data->file_block_no;

	//deleting old fd from all data structures
	nary_delete_node(&globaldata->root_nary, fd1);
	hashtable_delete_fd(&globaldata->hash_table, source_path->data);
	bst_delete(&globaldata->root_bst, source_path->data);

	bst_node *duplicate = bst_find(globaldata->root_bst, P2);
	if (duplicate == NULL ) {
		//adding new file in all data structures if the same fd does not already exists

		nary_insert_node(&globaldata->root_nary, fd);
		hashtable_insert(&globaldata->hash_table, fd);
		bst_insert(&globaldata->root_bst, fd);
	} else //else just update the datablock of the corresponding file
	{
		//decrementing num of used fd's and changing fd corresponding free list as empty
		globaldata->num_f_d_used = globaldata->num_f_d_used - 1;
		list l;
		fseek(fp,
				globaldata->freelistPoint
						+ ((duplicate->data->file_block_no) * sizeof(list)),
				SEEK_SET);
		l.isFull = 'n';
		l.block_num = fd->file_block_no;
		errno = 0;
		fwrite(&l, sizeof(list), 1, fp);
		if (strcmp(strerror(errno), "Success") != 0)
			printf("error in writing to datafile");

		strcpy(duplicate->data->file_name, fd->file_name);
		strcpy(duplicate->data->file_type, fd->file_type);
		strcpy(duplicate->data->file_path, P2);

		duplicate->data->file_size = fd->file_size;
		duplicate->data->start_addr = fd->start_addr;
		duplicate->data->file_block_no = fd->file_block_no;

	}
	/*printf("inorder in movefile");
	 inorder(globaldata->root_bst);*/
	return 0;
}

int vfscopyfile(char *P1, char *P2) {
	//inorder(globaldata->root_bst);
	// printf("status of ismounted is %d", ismounted);
	if (ismounted != 1) {
		return COPYFILE_VFS_NOT_MOUNTED;
	}

	FILE *fp;
	fp = fopen(globaldata->vfs_label, "rb+");

	//checking COPYFILE_FILE_SYSTEM_FULL
	if (globaldata->max_num_f_d == globaldata->num_f_d_used)
		return COPYFILE_FILE_SYSTEM_FULL;

	//checking MOVEFILE_CANNOT_FIND_SOURCEFILE and getting the fd for the corresponding file path
	bst_node *source_path;
	source_path = bst_find(globaldata->root_bst, P1);
	//temp = source_path;
	if (source_path == NULL )
		return COPYFILE_CANNOT_FIND_SOURCEFILE;

	//checking  COPYFILE_CANNOT_COPY_DIR_TO_FILE;
	if (strcmp(source_path->data->file_type, "DIR") == 0)
		return COPYFILE_CANNOT_COPY_DIR_TO_FILE;

	//checking  COPYFILE_CANNOT_FIND_DESTINATION_PATH;
	char file_path1[100];
	char * first = strchr(P2, '/');
	char * last = strrchr(P2, '/');
	if (strcmp(first, last) == 0) {
		strncpy(file_path1, last, 1);
		file_path1[strlen(last)] = '\0';
	} else {
		strncpy(file_path1, first, last - first);
		file_path1[last - first] = '\0';
	}
	bst_node *destination_path;
	destination_path = bst_find(globaldata->root_bst, file_path1);
	if (destination_path == NULL )
		return COPYFILE_CANNOT_FIND_DESTINATIONPATH;

	bst_node *duplicate = bst_find(globaldata->root_bst, P2);
	if (duplicate == NULL ) {
		//preparing new fd
		char *type = getFileType(P2);
		char *name = getFileName(P2);
		file_d* fd = prepareFileDescriptor(file_path1, name, type);
		int i;
		list l;
		//getting free block
		fseek(fp, globaldata->freelistPoint, SEEK_SET);
		for (i = 0; i < (globaldata->no_of_blocks); i++) {
			fread(&l, sizeof(list), 1, fp);
			if (l.isFull == 'n') {
				fd->file_block_no = l.block_num;
				break;
			}
		}
		//writing the updated data of the list back in the file
		fseek(fp, globaldata->freelistPoint + ((l.block_num) * sizeof(list)),
				SEEK_SET);
		l.isFull = 'y';
		fwrite(&l, sizeof(list), 1, fp);

		fd->start_addr = globaldata->datablkPoint
				+ ((fd->file_block_no) * globaldata->block_size);

		//creating data block and writing it to the vfs
		block blk;
		fseek(fp, source_path->data->start_addr, SEEK_SET);
		fread(&(blk.data), source_path->data->file_size, 1, fp);
		fd->file_size = source_path->data->file_size;
		fseek(fp, fd->start_addr, SEEK_SET);
		fwrite(&blk, sizeof(block), 1, fp);
		if (strcmp(strerror(errno), "Success") != 0)
			return ADDFILE_CANNOT_WRITE_TO_DATAFILE; //return something if error while writing
		//printf("Open error: %s\n\n", strerror(errno));
		fclose(fp);
		globaldata->num_f_d_used = globaldata->num_f_d_used + 1;

		//inserting in data structures
		int res = nary_insert_node(&globaldata->root_nary, fd);
		hashtable_insert(&globaldata->hash_table, fd);
		bst_insert(&globaldata->root_bst, fd);

	} else {
		//else just update the datablock of the corresponding file
		//decrementing num of used fd's and changing fd corresponding free list as empty

		block blk;
		fseek(fp, source_path->data->start_addr, SEEK_SET);
		fread(&(blk.data), source_path->data->file_size, 1, fp);
		duplicate->data->file_size = source_path->data->file_size;
		fseek(fp, duplicate->data->start_addr, SEEK_SET);
		fwrite(&blk, sizeof(block), 1, fp);
		if (strcmp(strerror(errno), "Success") != 0)
			return ADDFILE_CANNOT_WRITE_TO_DATAFILE; //return something if error while writing
		fclose(fp);

	}

	return 0;
}

int vfsexportfile(char *P1, char *P2) {
	if (ismounted != 1) {
		return EXPORTFILE_VFS_NOT_MOUNTED;
	}
	P1 = removeslash(P1);
	block blk;
	FILE *fp, *fp1;
	bst_node *find;

	//checking EXPORTFILE_CANNOT_FIND_SOURCEFILE
	find = bst_find(globaldata->root_bst, P1);
	if (find == NULL )
		return EXPORTFILE_CANNOT_FIND_SOURCEFILE;

	//checking EXPORTFILE_CANNOT_EXPORT_DIR
	if (strcmp(find->data->file_type, "DIR") == 0)
		return EXPORTFILE_CANNOT_EXPORT_DIR;

	//checking EXPORTFILE_CANNOT_CREATE_OUTPUTFILE
	fp1 = fopen(P2, "w+");
	if (fp1 == NULL )
		return EXPORTFILE_CANNOT_CREATE_OUTPUTFILE;

	fp = fopen(globaldata->vfs_label, "rb");
	if (find != NULL ) {
		fseek(fp, find->data->start_addr, SEEK_SET);
		fread(&blk, sizeof(block), 1, fp);
	}
	fwrite(&blk, find->data->file_size, 1, fp1);
	fclose(fp1);
	fclose(fp);
	return 0;

}

int vfssearchfile(char *P1, char *P2, int **count) {
	if (ismounted != 1) {
		return SEARCHFILE_VFS_NOT_MOUNTED;
	}
	//hash_table ht;
	l_node* result = NULL;
	//hashtable_print(&globaldata->hash_table);
	hashtable_search(&globaldata->hash_table, &result, P1);
	//printFileDescriptorLinkedList(result);
	FILE* fp = fopen(P2, "w");
	if (fp == NULL ) {
		return 11;
	}
	*count = 0;
	int cnt = 0;
	l_node *current = result;
	while (current != NULL ) {
		file_d* f = (file_d*) (current->data);
		if (strcmp((*f).file_type, "DIR") != 0) {
			char p[100];
			sprintf(p, "%s\n", (*f).file_path);
			cnt = cnt + 1;
			//printf("%s\n",p);
			fputs(p, fp);
		}
		current = current->next;
	}
	//printf("count is %d", cnt);
	(*count) = cnt;
	fclose(fp);
	//printf("Done\n");
	return 0;
}

int bst_path_cmp(bst_node *node, char* P1) {

	if (node != NULL ) {
		bst_path_cmp(node->left, P1);
		if (strncmp(node->data->file_path, P1, strlen(P1)) == 0
				&& node->data->file_path[strlen(P1)] == '/') {
			strcpy(bst_path[updatecount++], node->data->file_path);
		}
		bst_path_cmp(node->right, P1);
	}
	return updatecount;
}

void update_bst_ht(char* P1, char* P2) {
	updatecount = 0;
	int i;
	int res = bst_path_cmp(globaldata->root_bst, P1);
	/*	printf("Path %s  %s\n", P1, P2);
	 for (i = 0; i < updatecount; i++) {
	 printf("%s\n", bst_path[i]);
	 }*/
	for (i = 0; i < updatecount; i++) {
		char path[200];
		char name[200];
		bst_node *find = bst_find(globaldata->root_bst, bst_path[i]);
		if (find != NULL ) {
			file_d* duplicate = (file_d*) malloc(sizeof(file_d));
			sprintf(duplicate->file_name, "%s", find->data->file_name);
			sprintf(duplicate->file_path, "%s", find->data->file_path);
			duplicate->file_size = find->data->file_size;
			duplicate->start_addr = find->data->start_addr;
			duplicate->file_block_no = find->data->file_block_no;
			sprintf(duplicate->file_type, "%s", find->data->file_type);
			char* prefix = strrchr(find->data->file_path, '/');
			//		printf("before delete\n");
			//		inorder(globaldata->root_bst);
			//	hashtable_print(&globaldata->hash_table);
			hashtable_delete_fd(&globaldata->hash_table, find->data);
			bst_delete(&globaldata->root_bst, find->data);
			char file_path[200];
			char * first = strchr(P1, '/');
			char * last = strrchr(P1, '/');
			if (strcmp(first, last) == 0) {
				strncpy(file_path, last, 1);
				file_path[1] = '\0';
			} else {
				strncpy(file_path, first, last - first);
				file_path[last - first] = '\0';
			}
			int len = strlen(file_path);
			char finalpath[200];
			finalpath[0] = '\0';
			char* pointer = (bst_path[i] + len);
			if (strcmp(P2, "/") != 0) {
				strcpy(finalpath, P2);
			}
			if (pointer[0] != '/')
				strcat(finalpath, "/");
			strcat(finalpath, pointer);
			char sendpath[200];
			first = strchr(finalpath, '/');
			last = strrchr(finalpath, '/');
			if (strcmp(first, last) == 0) {
				strncpy(sendpath, last, 1);
				sendpath[1] = '\0';
			} else {
				strncpy(sendpath, first, last - first);
				sendpath[last - first] = '\0';
			}
			//		printf("\nafter before delete\n");
			//	hashtable_print(&globaldata->hash_table);
			//	inorder(globaldata->root_bst);
			/*strcpy(path, P2);
			 if(strcmp(P2,"/")!=0)
			 strcat(path, bst_path[i]);
			 prefix = strrchr(P1, '/');
			 strcat(path,prefix);
			 prefix = strrchr(duplicate->file_path, '/');
			 strcat(path,prefix);*/
//			char * first = strchr(P1, '/');
//			char * last = strrchr(P1, '/');
//			char finalpath[200];
//			if (strcmp(first, last) == 0) {
//				strncpy(file_path1, last, 1);
//				file_path1[strlen(last)] = '\0';
//
//
//				if (strcmp(P2, "/") != 0)
//					strcpy(finalpath, path);
//				else {
//					strcpy(finalpath, P2);
//					strcat(finalpath, bst_path[i]);
//
//				}
//
//			} else {
//				/*strncpy(file_path1, first, last - first);
//				file_path1[last - first] = '\0';
//				int len = strlen(file_path1);
//				char tempbstpath[200];
//				strcpy(tempbstpath, bst_path[i]);
//				strcpy(path, tempbstpath + len);
//				strcpy(finalpath, P2);
//				if (strcmp(P2, "/") != 0)
//					strcat(finalpath, "/");
//				strcat(finalpath, path);*/
//			}
			sprintf(duplicate->file_path, "%s", sendpath);
			bst_insert(&globaldata->root_bst, duplicate);
			hashtable_insert(&globaldata->hash_table, duplicate);
			//	printf("\nafter insert\n");
			//	inorder(globaldata->root_bst);
			//	hashtable_print(&globaldata->hash_table);
		}
	}
}

